/*
 *  Pedometer - Android App
 *  Copyright (C) 2009 Levente Bagi
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.m2dl.niptus.pathtrack.step;

import com.m2dl.niptus.pathtrack.utils.Constants;

import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

/**
 * This is an example of implementing an application service that runs locally
 * in the same process as the application. The {@link StepServiceController} and
 * {@link StepServiceBinding} classes show how to interact with the service.
 * 
 * <p>
 * Notice the use of the {@link NotificationManager} when interesting things
 * happen in the service. This is generally how background services should
 * interact with the user, rather than doing something more disruptive such as
 * calling startActivity().
 */
public class StepService extends Service {
	private final String TAG = Constants.TAG + "." + getClass().getSimpleName();

	private SharedPreferences mState;
	private SharedPreferences.Editor mStateEditor;

	private SensorManager mSensorManager;
	private StepDetector mStepDetector;

	private StepDisplayer mStepDisplayer;

	private int mSteps;

	/**
	 * Class for clients to access. Because we know this service always runs in
	 * the same process as its clients, we don't need to deal with IPC.
	 */
	public class StepBinder extends Binder {
		public StepService getService() {
			return StepService.this;
		}
	}

	@Override
	public void onCreate() {
		super.onCreate();
		Log.e(TAG, "onCreate");

		// Load settings
		mState = getSharedPreferences("state", 0);

		// Start detecting
		mStepDetector = new StepDetector(getApplicationContext());
		mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		registerDetector();

		mStepDisplayer = new StepDisplayer();
		mStepDisplayer.addListener(mStepListener);
		mStepDetector.addStepListener(mStepDisplayer);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		super.onStartCommand(intent, flags, startId);
		Log.e(TAG, "onStart");
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.e(TAG, "onDestroy");

		mStateEditor = mState.edit();
		mStateEditor.putInt("steps", mSteps);
		mStateEditor.commit();

		// Stop detecting
		mSensorManager.unregisterListener(mStepDetector);
		unregisterDetector();
	}

	private void registerDetector() {
		mSensorManager.registerListener(mStepDetector, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
		mSensorManager.registerListener(mStepDetector, mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_FASTEST);
	}

	private void unregisterDetector() {
		mSensorManager.unregisterListener(mStepDetector);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	/**
	 * Receives messages from activity.
	 */
	private final IBinder mBinder = new StepBinder();

	public interface ICallback {
		public void stepsChanged(int value);
	}

	private ICallback mCallback;

	public void registerCallback(ICallback cb) {
		mCallback = cb;
	}

	private StepDisplayer.Listener mStepListener = new StepDisplayer.Listener() {
		public void stepsChanged(int value) {
			mSteps = value;
			passValue();
		}

		public void passValue() {
			if (mCallback != null) {
				mCallback.stepsChanged(mSteps);
			}
		}
	};

}
